package com.microservice.wechat.scheduler;

import com.microservice.wechat.service.ArticleViewSyncService;
import com.microservice.common.utils.DistributedLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 文章阅读量定时同步调度器
 * 使用分布式锁防止多实例重复执行
 * 
 * @author wechat-service
 */
@Slf4j
@Component
@EnableScheduling
@ConditionalOnProperty(name = "wechat.sync.enabled", havingValue = "true", matchIfMissing = false)
public class ArticleViewSyncScheduler {

    @Autowired
    private ArticleViewSyncService articleViewSyncService;
    
    @Autowired
    private DistributedLock distributedLock;
    
    /**
     * 分布式锁的key
     */
    private static final String SYNC_LOCK_KEY = "wechat:article:sync:lock";

    /**
     * 每天早上7点执行文章阅读量同步
     * cron表达式: 秒 分 时 日 月 星期
     * 
     * 使用分布式锁确保在微服务集群环境下只有一个实例执行同步任务
     */
    @Scheduled(cron = "${wechat.sync.cron:0 0 7 * * ?}")
    public void syncArticleViewCount() {
        log.info("定时任务触发：尝试获取分布式锁执行文章阅读量同步");
        
        // 使用分布式锁执行任务，锁过期时间设置为2小时（同步任务预计时长）
        boolean executed = distributedLock.executeWithLock(
            SYNC_LOCK_KEY,
            2,
            TimeUnit.HOURS,
            () -> {
                try {
                    log.info("开始执行文章阅读量同步任务");
                    articleViewSyncService.syncAllArticles();
                    log.info("文章阅读量同步任务执行完成");
                } catch (Exception e) {
                    log.error("定时同步文章阅读量异常", e);
                }
            }
        );
        
        if (!executed) {
            log.info("其他实例正在执行同步任务，本实例跳过");
        }
    }

    /**
     * 手动触发同步（用于测试）
     * 可以通过接口调用此方法
     */
    public void manualSync() {
        log.info("手动触发：开始同步文章阅读量");
        articleViewSyncService.syncAllArticles();
    }
}
